////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Το παρόν περιέχει γενικές δομές και μεθόδους που αφορούν τόσο στον server
// όσο και στους clients, αλλά είναι εξειδικευμένες στoν «Πρεφαδόρο». Όλα τα
// σχετικά εντάσσονται στο singleton "Prefadoros".

Prefadoros = {
	// Η property "thesiMax" δείχνει τον μέγιστο αριθμό θέσης στο τραπέζι.
	// Μπορεί να φαίνεται υπερβολικό, αλλά βολεύει σε αλλαγή παιχνιδιού.

	thesiMax: 3,

	// Χρησιμοποιούμε το associative array "thesiValid" για να διατρέχουμε
	// τις θέσεις του τραπεζιού (η σειρά δεν είναι εγγυημένη από τη γλώσσα).

	thesiValid: {},

	// Η μέθοδος "isThesi" δέχεται ένα όρισμα και ελέγχει αν το όρισμα αυτό
	// είναι δεκτό ως θέση τραπεζιού.

	isThesi: function(thesi) {
		return Prefadoros.thesiValid[thesi];
	},

	// Η μέθοδος "oxiThesi" δέχεται ένα όρισμα και ελέγχει αν το όρισμα αυτό
	// δεν είναι δεκτό ως θέση τραπεζιού.

	oxiThesi: function(thesi) {
		return !Prefadoros.isThesi(thesi);
	},

	fetchThesi: function(thesi) {
		if (Prefadoros.isThesi(thesi)) return Prefadoros.thesiValid[thesi];
		globals.fatal('Prefadoros.fetchThesi: ' + thesi + ': απαράδεκτη θέση');
	},

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

	// Οι παρακάτω δομές και μέθοδοι βοηθούν στην οικονομικότερη διακίνηση
	// δεδομένων που αφορούν στα τραπέζια.

	trapeziEcoMap: {
		'kodikos': 'k',
		'stisimo': 's',
		'pektis1': 'p1',
		'apodoxi1': 'a1',
		'pektis2': 'p2',
		'apodoxi2': 'a2',
		'pektis3': 'p3',
		'apodoxi3': 'a3',
		'trparam': 'r',
		'dianomi': 'd',
	},

	trapeziOceMap: {},

	trapeziEco: function(attr) {
		if (this.trapeziEcoMap.hasOwnProperty(attr)) return this.trapeziEcoMap[attr];
		globals.fatal(attr + ': attribute not in "trapeziEcoMap"');
	},

	trapeziOce: function(attr) {
		if (this.trapeziOceMap.hasOwnProperty(attr)) return this.trapeziOceMap[attr];
		globals.fatal(attr + ': attribute not in "trapeziOceMap"');
	},

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

	// Οι παρακάτω δομές και μέθοδοι βοηθούν στην οικονομικότερη διακίνηση
	// δεδομένων που αφορούν στις παραμέτρους των τραπεζιών.

	trparamEcoMap: {
		'ΚΑΣΑ': 'k',
		'ΑΣΟΙ': 'a',
		'ΠΑΣΟ': 'p',
		'ΤΕΛΕΙΩΜΑ': 'e',
		'ΠΡΙΒΕ': 'v',
		'ΑΝΟΙΚΤΟ': 'o',
		'ΦΙΛΙΚΗ': 'f',
		'ΕΠΕΤΕΙΑΚΗ': 'c',
		'ΙΔΙΟΚΤΗΤΟ': 'i',
	},

	trparamOceMap: {},

	trparamEco: function(attr) {
		if (this.trparamEcoMap.hasOwnProperty(attr)) return this.trparamEcoMap[attr];
		globals.fatal(attr + ': attribute not in "trparamEco"');
	},

	trparamOce: function(attr) {
		if (this.trparamOceMap.hasOwnProperty(attr)) return this.trparamOceMap[attr];
		globals.fatal(attr + ': attribute not in "trparamOce"');
	},

	trparamDecode: function(param, timi) {
		switch (param) {
		case 'ΚΑΣΑ':
			if (((typeof timi) == 'number') && (parseInt(timi) == timi)) return timi;
			break;
		case 'ΤΕΛΕΙΩΜΑ':
			switch (timi) {
			case 'N': return 'ΚΑΝΟΝΙΚΟ';
			case 'U': return 'ΑΝΙΣΟΡΡΟΠΟ';
			case 'F': return 'ΔΙΚΑΙΟ';
			}
			break;
		case 'ΑΣΟΙ':
		case 'ΠΑΣΟ':
		case 'ΠΡΙΒΕ':
		case 'ΑΝΟΙΚΤΟ':
		case 'ΦΙΛΙΚΗ':
		case 'ΕΠΕΤΕΙΑΚΗ':
		case 'ΙΔΙΟΚΤΗΤΟ':
			switch (timi) {
			case 0: return 'ΟΧΙ';
			case 1: return 'ΝΑΙ';
			}
			break;
		default:
			globals.fatal('Prefadoros.trparamDecode: ' + param + ': άγνωστη παράμετρος');
		}

		globals.fatal('Prefadoros.trparamDecode: ' + timi + ': λανθασμένη τιμή για την παράμετρο "' + param + '"');
	},

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

	// Οι παρακάτω δομές και μέθοδοι βοηθούν στην οικονομικότερη διακίνηση
	// δεδομένων που αφορούν στις συνεδρίες.

	sinedriaEcoMap: {
		'pektis': 'p',
		'ip': 'i',
		'isodos': 's',
		'trapezi': 't',
		'thesi': 'h',
		'theatis': 'v',
	},

	sinedriaOceMap: {},

	sinedriaEco: function(attr) {
		if (this.sinedriaEcoMap.hasOwnProperty(attr)) return this.sinedriaEcoMap[attr];
		globals.fatal(attr + ': attribute not in "sinedriaEcoMap"');
	},

	sinedriaOce: function(attr) {
		if (this.sinedriaOceMap.hasOwnProperty(attr)) return this.sinedriaOceMap[attr];
		globals.fatal(attr + ': attribute not in "sinedriaOceMap"');
	},

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

	// Οι παρακάτω δομές και μέθοδοι βοηθούν στην οικονομικότερη διακίνηση
	// δεδομένων που αφορούν στους παίκτες.

	pektisEcoMap: {
		'onoma': 'o',
		'peparam': 'r',
	},

	pektisOceMap: {},

	pektisEco: function(attr) {
		if (this.pektisEcoMap.hasOwnProperty(attr)) return this.pektisEcoMap[attr];
		globals.fatal(attr + ': attribute not in "pektisEcoMap"');
	},

	pektisOce: function(attr) {
		if (this.pektisOceMap.hasOwnProperty(attr)) return this.pektisOceMap[attr];
		globals.fatal(attr + ': attribute not in "pektisOceMap"');
	},

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

	// Οι παρακάτω δομές και μέθοδοι βοηθούν στην οικονομικότερη διακίνηση
	// δεδομένων που αφορούν στις παραμέτρους των παικτών.

	peparamEcoMap: {
		'ΑΞΙΩΜΑ': 'x',
		'ΚΑΤΑΣΤΑΣΗ': 's',
		'ΠΛΑΤΗ': 'l',
		'ΠΑΡΑΣΚΗΝΙΟ': 'b',
		'BLOCKIMAGE': 'i',
		'MOVIETIME': 't',
		'MOVIESCALE': 'm',
		'ΑΣΟΙ': 'a',
		'ΠΑΣΟ': 'p',
		'ΤΕΛΕΙΩΜΑ': 'e',
	},

	peparamOceMap: {},

	peparamEco: function(attr) {
		if (this.peparamEcoMap.hasOwnProperty(attr)) return this.peparamEcoMap[attr];
		globals.fatal(attr + ': attribute not in "peparamEco"');
	},

	peparamOce: function(attr) {
		if (this.peparamOceMap.hasOwnProperty(attr)) return this.peparamOceMap[attr];
		globals.fatal(attr + ': attribute not in "peparamOce"');
	},

	peparamDimosiaMap: {
		'ΑΞΙΩΜΑ': 1,
		'ΚΑΤΑΣΤΑΣΗ': 1,
		'ΑΣΟΙ': 1,
		'ΠΑΣΟ': 1,
		'ΤΕΛΕΙΩΜΑ': 1,
	},

	peparamDimosia: function(param) {
		return this.peparamDimosiaMap.hasOwnProperty(param);
	},

	peparamIdiotiki: function(param) {
		return !this.peparamDimosia(param);
	},

	peparamDecode: function(param, timi) {
		switch (param) {
		case 'ΑΞΙΩΜΑ':
			switch (timi) {
			case 0: return 'ΘΑΜΩΝΑΣ';
			case 1: return 'VIP';
			case 2: return 'ΕΠΟΠΤΗΣ';
			case 3: return 'ΔΙΑΧΕΙΡΙΣΤΗΣ';
			case 4: return 'ADMINISTRATOR';
			case 5: return 'ΠΡΟΕΔΡΟΣ';
			}
			break;
		case 'ΤΕΛΕΙΩΜΑ':
			switch (timi) {
			case 'U': return 'ΑΝΙΣΟΡΡΟΠΟ';
			case 'F': return 'ΔΙΚΑΙΟ';
			case 'N': return 'ΚΑΝΟΝΙΚΟ';
			}
			break;
		case 'ΠΛΑΤΗ':
			switch (timi) {
			case 'B': return 'ΜΠΛΕ';
			case 'R': return 'ΚΟΚΚΙΝΟ';
			case 'N': return 'ΤΥΧΑΙΟ';
			}
			break;
		case 'ΚΑΤΑΣΤΑΣΗ':
			switch (timi) {
			case 'A': return 'ΔΙΑΘΕΣΙΜΟΣ';
			case 'B': return 'ΑΠΑΣΧΟΛΗΜΕΝΟΣ';
			}
			break;
		case 'ΠΑΡΑΣΚΗΝΙΟ':
			if ((typeof timi) == 'string') return timi;
			break;
		case 'MOVIETIME':
			switch (timi) {
			case 'M': return 'ΜΕΤΡΟΝΟΜΟΣ';
			case 'R': return 'ΠΡΑΓΜΑΤΙΚΟΣ';
			}
			break;
		case 'MOVIESCALE':
			if (((typeof timi) == 'number') && (parseInt(timi) == timi) && (timi > 0)) return timi;
			break;
		case 'ΑΣΟΙ':
		case 'ΠΑΣΟ':
		case 'BLOCKIMAGE':
			switch (timi) {
			case 0: return 'ΟΧΙ';
			case 1: return 'ΝΑΙ';
			}
			break;
		default:
			globals.fatal('Pektis.peparamDecode: ' + param + ': invalid "param"');
		}

		globals.fatal('Pektis.peparamDecode: ' + timi + ': invalid "timi" for "' + param + '"');
	},

	peparamEncode: function(param, timi) {
		switch (param) {
		case 'ΑΞΙΩΜΑ':
			switch (timi) {
			case 'ΘΑΜΩΝΑΣ': return 0;
			case 'VIP': return 1;
			case 'ΕΠΟΠΤΗΣ': return 2;
			case 'ΔΙΑΧΕΙΡΙΣΤΗΣ': return 3;
			case 'ADMINISTRATOR': return 4;
			case 'ΠΡΟΕΔΡΟΣ': return 5;
			}
			break;
		case 'ΤΕΛΕΙΩΜΑ':
			switch (timi) {
			case 'ΑΝΙΣΟΡΡΟΠΟ': return 'U';
			case 'ΔΙΚΑΙΟ': return 'F';
			case 'ΚΑΝΟΝΙΚΟ': return 'N';
			}
			break;
		case 'ΠΛΑΤΗ':
			switch (timi) {
			case 'ΜΠΛΕ': return 'B';
			case 'ΚΟΚΚΙΝΟ': return 'R';
			case 'ΤΥΧΑΙΟ': return 'N';
			}
			break;
		case 'ΚΑΤΑΣΤΑΣΗ':
			switch (timi) {
			case 'ΔΙΑΘΕΣΙΜΟΣ': return 'A';
			case 'ΑΠΑΣΧΟΛΗΜΕΝΟΣ': return 'B';
			}
			break;
		case 'ΠΑΡΑΣΚΗΝΙΟ':
			if ((typeof timi) == 'string') return timi;
			break;
		case 'MOVIETIME':
			switch (timi) {
			case 'ΜΕΤΡΟΝΟΜΟΣ': return 'M';
			case 'ΠΡΑΓΜΑΤΙΚΟΣ': return 'R';
			}
			break;
		case 'MOVIESCALE':
			if (((typeof timi) == 'number') && (parseInt(timi) == timi) && (timi > 0)) return timi;
			break;
		case 'ΑΣΟΙ':
		case 'ΠΑΣΟ':
		case 'BLOCKIMAGE':
			switch (timi) {
			case 'ΟΧΙ': return 0;
			case 'ΝΑΙ': return 1;
			}
			break;
		default:
			globals.fatal('Pektis.peparamEncode: ' + param + ': invalid "param"');
		}

		globals.fatal('Pektis.peparamEncode: ' + timi + ': invalid "timi" for "' + param + '"');
	},

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

	// Οι παρακάτω δομές και μέθοδοι βοηθούν στην οικονομικότερη διακίνηση
	// δεδομένων που αφορούν στις διανομές.

	dianomiEcoMap: {
		'kodikos': 'k',
		'trapezi': 't',
		'enarxi': 'e',
		'dealer': 'l',
		'kasa1': 'k1',
		'metrita1': 'm1',
		'kasa2': 'k2',
		'metrita2': 'm2',
		'kasa3': 'k3',
		'metrita3': 'm3',
	},

	dianomiOceMap: {},

	dianomiEco: function(attr) {
		if (this.dianomiEcoMap.hasOwnProperty(attr)) return this.dianomiEcoMap[attr];
		globals.fatal(attr + ': attribute not in "dianomiEco"');
	},

	dianomiOce: function(attr) {
		if (this.dianomiOceMap.hasOwnProperty(attr)) return this.dianomiOceMap[attr];
		globals.fatal(attr + ': attribute not in "dianomiOce"');
	},

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

	// Οι παρακάτω δομές και μέθοδοι βοηθούν στην οικονομικότερη διακίνηση
	// δεδομένων που αφορούν στις διανομές.

	energiaEcoMap: {
		'dianomi': 'd',
		'pektis': 'p',
		'idos': 'i',
		'data': 'D',
		'pote': 'w',
	},

	energiaOceMap: {},

	energiaEco: function(attr) {
		if (this.energiaEcoMap.hasOwnProperty(attr)) return this.energiaEcoMap[attr];
		globals.fatal(attr + ': attribute not in "energiaEco"');
	},

	energiaOce: function(attr) {
		if (this.energiaOceMap.hasOwnProperty(attr)) return this.energiaOceMap[attr];
		globals.fatal(attr + ': attribute not in "energiaOce"');
	},

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

	// Οι παρακάτω δομές και μέθοδοι βοηθούν στην οικονομικότερη διακίνηση
	// δεδομένων που αφορούν στις ενέργειες.

	energiaIdosEcoMap: {
		'ΔΙΑΝΟΜΗ': 'd',
		'ΔΗΛΩΣΗ': 'l',
		'ΤΖΟΓΟΣ': 'z',
		'ΣΟΛΟ': 'L',
		'ΑΓΟΡΑ': 'a',
		'ΣΥΜΜΕΤΟΧΗ': 's',
	},

	energiaIdosOceMap: {},

	energiaIdosEco: function(attr) {
		if (this.energiaIdosEcoMap.hasOwnProperty(attr)) return this.energiaIdosEcoMap[attr];
		globals.fatal(attr + ': attribute not in "energiaIdosEco"');
	},

	energiaIdosOce: function(attr) {
		if (this.energiaIdosOceMap.hasOwnProperty(attr)) return this.energiaIdosOceMap[attr];
		globals.fatal(attr + ': attribute not in "energiaIdosOce"');
	},

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

	// Το property "anazitisiMax" περιορίζει τα επιστρεφόμενα αποτελέσματα
	// κατά την αναζήτηση παικτών. Αν τα αποτελέσματα είναι περισσότερα από
	// αυτό το όριο, τότε περικόπτονται. Το όριο πρέπει να είναι γνωστό στον
	// server, ώστε να κάνει την περικοπή, αλλά πρέπει να είναι γνωστό και
	// στον client ώστε να εμφανίζει σχετική ειδοποίηση όταν το πλήθος των
	// αποτελεσμάτων προεσγγίζει το όριο.

	anazitisiMax: 100,

	// Ακολουθεί το default χρονικό περιθώριο στο οποίο μια συνεδρία θεωρείται
	// νέα και θα εμφανίζεται στο χώρο τών νεοφερμένων.

	niofertosTimeout: 300,

	maxSxolia: 60,

	minSxolia: 40,

	sxolioKodikos: {
		moliviKafenio: '@VK@',
		moliviTrapezi: '@VT@',
		korna: '@KN@',
	},
};

// Έχουν καθοριστεί οι πίνακες αντιστοίχισης ονομασίας διαφόρων χαρακτηριστικών
// σε οικονομικότερες ονομασίες. Με βάση αυτούς τους πίνακες θα δημιουργήσω τώρα
// τους αντίστροφους πίνακες.

(function() {
	var i;
	for (i = 1; i <= Prefadoros.thesiMax; i++) Prefadoros.thesiValid[i] = i;
	for (i in Prefadoros.trapeziEcoMap) Prefadoros.trapeziOceMap[Prefadoros.trapeziEcoMap[i]] = i;
	for (i in Prefadoros.trparamEcoMap) Prefadoros.trparamOceMap[Prefadoros.trparamEcoMap[i]] = i;
	for (i in Prefadoros.sinedriaEcoMap) Prefadoros.sinedriaOceMap[Prefadoros.sinedriaEcoMap[i]] = i;
	for (i in Prefadoros.pektisEcoMap) Prefadoros.pektisOceMap[Prefadoros.pektisEcoMap[i]] = i;
	for (i in Prefadoros.peparamEcoMap) Prefadoros.peparamOceMap[Prefadoros.peparamEcoMap[i]] = i;
	for (i in Prefadoros.dianomiEcoMap) Prefadoros.dianomiOceMap[Prefadoros.dianomiEcoMap[i]] = i;
	for (i in Prefadoros.energiaEcoMap) Prefadoros.energiaOceMap[Prefadoros.energiaEcoMap[i]] = i;
	for (i in Prefadoros.energiaIdosEcoMap) Prefadoros.energiaIdosOceMap[Prefadoros.energiaIdosEcoMap[i]] = i;
})();

// Η μέθοδος "epomenosPektis" εφαρμόζεται πάνω στη θέση κάποιου παίκτη και
// επιστρέφει την επόμενη θέση.

Number.prototype.epomenosPektis = function() {
	var thesi;

	if (!Prefadoros.thesiValid.hasOwnProperty(this)) globals.fatal('epomenosPektis: ' + this + ': ακαθόριστη θέση παίκτη');
	thesi = this.valueOf() + 1;
	if (thesi > Prefadoros.thesiMax) thesi = 1;
	return thesi;
}

// Η μέθοδος "isDexia" εφαρμόζεται πάνω στη θέση κάποιου παίκτη και επιστρέφει
// true αν η θέση αυτή βρίσκεται δεξιά από τη θέση που περνάμε ως παράμετρο.

Number.prototype.isDexia = function(thesi) {
	return thesi.epomenosPektis() == this;
}

// Η μέθοδος "isAristera" εφαρμόζεται πάνω στη θέση κάποιου παίκτη και επιστρέφει
// true αν η θέση αυτή βρίσκεται αριστερά από τη θέση που περνάμε ως παράμετρο.

Number.prototype.isAristera = function(thesi) {
	return this.epomenosPektis() == thesi;
}

String.prototype.epomenoXroma = function() {
	switch (this.valueOf()) {
	case 'S': return 'C';
	case 'C': return 'D';
	case 'D': return 'H';
	case 'H': return 'N';
	}

	globals.fatal('epomenoXroma: ' + this + ': ακαθόριστο επόμενο χρώμα');
}
